package com.android.prpltalk;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java.util.Iterator;



/**
* Provides conversation sessions management functionalities.
* In particular, it allows the creation of a new conversation 
* session and the removal of an existing one, retrieving 
* existing sessions, adding messages to a session and so on.
*/
public class ChatSessionManager 
{
	
	/** 
	 * The instance of the chat session manager 
	 */
	private static ChatSessionManager instance = new ChatSessionManager(); 
	
	/** 
	 * The session map. Each session is stored using its ID as a map key. 
	 */
	private Map<String,ChatSession> sessionMap; 
	
	
	
	/** 
	 * Max number of chat sessions 
	 */
	public static final int MAX_CHAT_SESSION_NUMBER = 8; 
	

	private ChatSessionManager()
	{
		sessionMap = new HashMap<String, ChatSession>(MAX_CHAT_SESSION_NUMBER);
	}
	
	/**
	 * Gets the instance of the ChatSessionManager.
	 * 
	 * @return the instance of the ChatSessionManager
	 */
	public static ChatSessionManager getInstance()
	{
		return instance;
	}

	
	/**
	 * Called when the user initiates a session with other contacts, 
	 * creates a new session generating the session ID from the 
	 * participants ID list. The session is then added to the session 
	 * map and its session ID is returned. 
	 * 
	 * @param prpl_sessionID Session ID generated and given by PrPl
	 * @param participantIds the list of participants ids (emails)
	 * @return String that represents the session Id for the newly created session
	 */
	public String startChatSession(String prpl_sessionID, List<String> participantIds)
	{
		// String sessionIdAsString = getSessionIdFromParticipants(participantIds);
		addChatSession(prpl_sessionID, participantIds);
		return prpl_sessionID;
	}
	
	
	/**
	 * Gets the session ID from participants ID list.
	 * Session ID is computed by hashing each participant's email 
	 * and then by exoring them all together.
	 * This should create a fairly unique values that depends 
	 * only from the participants IDs and not by the order
	 * in which they appear.  
	 * 
	 * @param participantIds the list of participant emails
	 * @return the session id as a string
	 */
	/*
	public String getSessionIdFromParticipants(List<String> participantIds)
	{		
		String myContactId 
		= ContactManager.getInstance().getMyContact().getEmail();
		
		//The session id is computed by hashing agentNames
		int sessionIdAsInt= myContactId.hashCode();	
		for (String participantId : participantIds) 
		{
			int tmp = participantId.hashCode();
			sessionIdAsInt ^= tmp;
		}
		
		String sessionIdAsStr = String.valueOf(sessionIdAsInt);
		return sessionIdAsStr;
	}
	*/


	/**
	 * Adds a new chat session initiated by another contact 
	 * (the other contact starts the communication, not you)
	 * 
	 * @param sessionId Session ID generated and given by PrPl
	 * @param participantIds the list of all participants' ids/emails
	 */
	public synchronized void addChatSession(String sessionId, 
											List<String> participantIds)
	{
		if (!sessionMap.containsKey(sessionId))
		{
			int sessionCounter = sessionMap.size()+1;
			ChatSession session
			= new ChatSession(sessionId, participantIds, sessionCounter);

			// register it
			sessionMap.put(sessionId, session);
		}
	}
	
	
	/**
	 * Adds a new conversation session initiated by another 
	 * contact (the other contact start the communication)
	 * 
	 * @param sessionId the session id
	 * @param recvIt the iterator over the receiver list
	 * @param senderEmail the email of the contact 
	 *                    that initiates the session 
	 */
	public synchronized void addChatSession(String sessionId,
											Iterator<String> recvIt,
											String senderEmail)
	{
		if (!sessionMap.containsKey(sessionId))
		{
			// sessionCounter denotes what # this conversation is
			int sessionCounter = sessionMap.size()+1;
			ChatSession session 
			= new ChatSession(sessionId, recvIt, senderEmail, sessionCounter); 
			
			//register it
			sessionMap.put(sessionId, session);	
		}
	}
	
	
	/**
	 * Removes an active session given its ID. 
	 * @param msnSession the session id
	 */
	public synchronized void removeChatSession(String sessionId)
	{		
		sessionMap.remove(sessionId);		
	}


	/**
	 * Retrieve a copy of a session, given its id.
	 * 
	 * @param sessionId id of the session we would like to retrieve 
	 * @return the copy of the desired session
	 */
	public ChatSession retrieveSession(String sessionId)
	{
		ChatSession session = null;

		synchronized (this)
		{
			session = sessionMap.get(sessionId);
		}
		
		return session;			
	}


	/**
	 * Performs some cleanup
	 */
	public synchronized void shutdown()
	{
		sessionMap.clear();
	}


	/**
	 * Retrieves the list of participants to all active 
	 * session in a given moment (useful for changing 
	 * map icon to contacts that are in an active session)
	 * 
	 * @return the list of ids of all contacts participating 
	 *         in a chat session.
	 */
	public synchronized Set<String> getAllParticipantIds()
	{
		//define a set to avoid duplicates
		Set<String> idSet = new HashSet<String>();
		ArrayList<ChatSession> c = null;
		
		synchronized(this)
		{
			c = new ArrayList<ChatSession>(sessionMap.values()); 
		}
		
		for (ChatSession session : c) 
		{
			List<String> partIds = session.getAllParticipantIds();
			idSet.addAll(partIds);
		}
		
		return idSet;
	}

}
  
